<?php

namespace backend\widgets\Chart;

use yii\base\Widget;
use yii\data\SqlDataProvider;
use yii\helpers\Json;

class ChartWidget extends Widget
{
    public $event_id;
    private $allWeekSales;
    private $onlineSales;
    private $offlineSales;

    public function init()
    {
        $this->allWeekSales = \Yii::$app->db->createCommand('
            SELECT YEAR(`date_sale`) as year_sale, WEEK(`date_sale`, 1) as week_sale
            FROM ticket_sales 
            WHERE event_id=:event_id
            GROUP BY YEAR(`date_sale`), WEEK(`date_sale`, 1)
        ', [':event_id' => $this->event_id])->queryAll();

        $this->onlineSales = \Yii::$app->db->createCommand('
            SELECT YEAR(`date_sale`) as year_sale, WEEK(`date_sale`, 1) as week_sale, MIN(`date_sale`) as week_date_start, MAX(`date_sale`) as week_date_end, SUM(`tariff`) as summ, COUNT(*) as count
            FROM ticket_sales 
            WHERE event_id=:event_id AND is_online_sale=:online_sale
            GROUP BY YEAR(`date_sale`), WEEK(`date_sale`, 1)
        ', [':event_id' => $this->event_id, ':online_sale' => \backend\models\TicketSales::ONLINE_SALE])->queryAll();

        $this->offlineSales = \Yii::$app->db->createCommand('
            SELECT YEAR(`date_sale`) as year_sale, WEEK(`date_sale`, 1) as week_sale, MIN(`date_sale`) as week_date_start, MAX(`date_sale`) as week_date_end, SUM(`tariff`) as summ, COUNT(*) as count
            FROM ticket_sales 
            WHERE event_id=:event_id AND is_online_sale=:online_sale
            GROUP BY YEAR(`date_sale`), WEEK(`date_sale`, 1)
        ', [':event_id' => $this->event_id, ':online_sale' => \backend\models\TicketSales::OFFLINE_SALE])->queryAll();

        parent::init();
    }

    public function run()
    {   
        $this->registerPlugin();
        echo '<div>
              <canvas id="myChart"></canvas>
          </div>';
    }

    protected function registerPlugin()
    {
        $view = $this->getView();

        ChartAsset::register($view);
        
        $jsonAllWeekSales = Json::encode($this->allWeekSales);
        $jsonOnlineSales = Json::encode($this->onlineSales);
        $jsonOfflineSales = Json::encode($this->offlineSales);

        $view->registerJs("const ctx = document.getElementById('myChart');
            

            const dataOnlineSales = " . $jsonOnlineSales . ";
            const dataOfflineSales = " . $jsonOfflineSales . ";
            const dataAllWeekSales = " . $jsonAllWeekSales . ";

            const onlineSales_Format = [];
            const offlineSales_Format = [];

            const data = [];

            // наполняем офлайн продажи
            for(i = 0; i < dataAllWeekSales.length; i++)
            {
                let existingWeek_inOffline = dataOfflineSales.find((o) => {
                    if (o.week_sale == dataAllWeekSales[i].week_sale && o.year_sale == dataAllWeekSales[i].year_sale) {
                        return true; // stop searching
                    }
                });

                if(existingWeek_inOffline) {
                    offlineSales_Format.push(existingWeek_inOffline);
                }
                else {
                    offlineSales_Format.push({
                        'week_sale': dataAllWeekSales[i].week_sale,
                        'year_sale': dataAllWeekSales[i].year_sale,
                        'count': 0,
                        'summ': 0
                    });
                }
            }

            // наполняем онлайн продажи
            for(i = 0; i < dataAllWeekSales.length; i++)
            {
                let existingWeek_inOnline = dataOnlineSales.find((o) => {
                    if (o.week_sale == dataAllWeekSales[i].week_sale && o.year_sale == dataAllWeekSales[i].year_sale) {
                        return true; // stop searching
                    }
                });

                if(existingWeek_inOnline) {
                    onlineSales_Format.push(existingWeek_inOnline);
                }
                else {
                    onlineSales_Format.push({
                        'week_sale': dataAllWeekSales[i].week_sale,
                        'year_sale': dataAllWeekSales[i].year_sale,
                        'count': 0,
                        'summ': 0
                    });
                }
            }

            data.push(onlineSales_Format);
            data.push(offlineSales_Format);
            
            new Chart(ctx, {
              type: 'bar',
              data: {
                labels: onlineSales_Format.map(row => row.week_sale),
                datasets: [{
                    label: 'Онлайн продажи',
                    data: onlineSales_Format.map(row => row.summ),
                    borderWidth: 1
                },
                {
                    label: 'Офлайн продажи',
                    data: offlineSales_Format.map(row => row.summ),
                    borderWidth: 1
                }]
              },
              options: {
                interaction: {
                    intersect: false,
                    mode: 'index',
                },
                scales: {
                    x: {
                        stacked: true,
                    },
                    y: {
                        beginAtZero: true,
                        stacked: true,
                    }
                },
                plugins: {
                    tooltip: {
                        callbacks: {
                            title: function(context) {
                                let title = context[0].label;
                                return 'Неделя ' + title + ' - ' + onlineSales_Format[context[0]['dataIndex']]['year_sale'] + ' год';
                            },
                            label: function(context) {
                                let label = context.dataset.label || '';
        
                                if (label) {
                                    label += ': ';
                                }
                                if (context.parsed.y !== null) {
                                    label += new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' }).format(context.parsed.y);
                                }
                                return label;
                            },
                            afterLabel: function(context) {
                                return 'Билетов: ' + data[context['datasetIndex']][context['dataIndex']]['count'] + ' шт.';
                            },
                            beforeBody: function(context) {
                                const firstDayOfYear = new Date(onlineSales_Format[context[0]['dataIndex']]['year_sale'], 0, 1);  // Получаем первый день года
                                const daysToAdd = (onlineSales_Format[context[0]['dataIndex']]['week_sale'] - 1) * 7;  // Вычисляем сколько дней добавить к первому дню года
                                const startDate = new Date(firstDayOfYear.getTime() + daysToAdd * 24 * 60 * 60 * 1000);  // Получаем начальную дату
                                const endDate = new Date(startDate.getTime() + 6 * 24 * 60 * 60 * 1000);  // Получаем конечную дату

                                const lineArr = [];
                                lineArr.push(new Intl.DateTimeFormat('ru', {year: 'numeric', month: 'long', day: 'numeric'}).format(startDate));
                                lineArr.push(new Intl.DateTimeFormat('ru', {year: 'numeric', month: 'long', day: 'numeric'}).format(endDate));
                                lineArr.push('');
                                return lineArr;
                            },
                            footer: function(tooltipItems)  {
                                const lineArr = [];
                                let sum = 0;
                                let count = 0;
                                tooltipItems.forEach(function(tooltipItem, i) {
                                    sum += tooltipItem.parsed.y;
                                    count += Number(data[i][tooltipItem['dataIndex']]['count']);
                                });
                                sum = new Intl.NumberFormat('ru-RU', { style: 'currency', currency: 'RUB' }).format(sum);
                                lineArr.push('Сумма: ' + sum);
                                lineArr.push('Билетов: ' + count + ' шт.');

                                return lineArr;
                            }
                        }
                    }
                }
              }
            });");
        }

}
